(function() {
    this.initPrinter = function(type,options){
        switch (type) {
            case 'shopex':
                return new ShopexPrinter(options);
            case 'cainiao':
                return new CaiNiaoPrinter(options);
            case 'pdd':
                return new PddPrinter(options);
            case 'lodop':
                return new LodopPrinter(options);
        }

        return null;
    };

    var Printer = new Class({
        Implements: [Events, Options],
        options:{
            data:{},      // 打印数据
            template:'',  // 打印模板
            template_url:'',
            custom_template_url:'',
            custom_data:{},
            activex:null,// 控件
            type:'express'// 单据类型
            /*
            onPrintSuccess: function(responseText){},
            onPreview: function(responseText){},
            onGetPrinters: function(responseText){},
            onPrintComplete: function(responseText){},
            onPrinterConfig:function(){},
            onOpen:function(){},
            onClose:function(){},
            onError:function(){},
            onMoveto:function(){}*/
        },
        initialize: function(options){
            this.setOptions(options);
        },
        print:function(printer){},
        preview:function(printer){},
        getPrinters:function(){},
        setPrinterConfig:function(printer){},
        moveto:function(page){},
        isReady:function(){},
        loadReport:function(data,template){},
        setPrinters:function(element,data){
            var offsetx = element.getParent('#print-preview').getElement('#offsetx');
            var offsety = element.getParent('#print-preview').getElement('#offsety');
            var thermal = element.getParent('#print-preview').getElement('#thermal');

            if (!data.printerlist) return 0;

            var select = new Element('select',{
                id:'printerlist',
                name:'printerlist',
                class:'x-input-select inputstyle',
                styles:{
                    width:'width:130px;'
                },
                events:{
                    change:function(){
                        var optionSelected  = this.getElement('option:selected');

                        // 设置偏移量
                        if ($defined(offsetx)) offsetx.set('value',optionSelected.get('x'));

                        if ($defined(offsety)) offsety.set('value',optionSelected.get('y'));

                        // 设置热敏
                        if ($defined(thermal)) thermal.set('checked', optionSelected.get('isThermal')?true:false);
                    }
                }
            });

            var optionDefault = [];
            data.printerlist.each(function(printer){
                var option = new Element('option',{
                    value:printer.printername,
                    text:printer.printername,
                    selected:data.default==printer.printername?true:false,
                    x:printer.x,
                    y:printer.y,
                    isThermal:printer.isThermal
                });
                select.adopt(option);

                // 自动匹配打印机
                // if (printer.printername.contains("<{$express_company_no|default:0123456789}>")) {
                //     optionDefault[2] = option;
                // }

                if (data.lastSelected.express == printer.printername) {
                    optionDefault[1] = option;
                }

                if (data.default == printer.printername) {
                    optionDefault[0] = option;
                }
            });

            if (optionDefault.length) {
                var optionSelected = optionDefault.getLast();

                optionSelected.selected=true;

                // 设置偏移量
                if ($defined(offsetx)) offsetx.set('value',optionSelected.get('x'));

                if ($defined(offsety)) offsety.set('value',optionSelected.get('y'));

                // 设置热敏
                if ($defined(thermal)) thermal.set('checked', optionSelected.get('isThermal')?true:false);
            }

            element.adopt(select);

            return data.printerlist.length;
        }
    });

    /**
     * 商派打印控件
     * @param  {[type]} ){                                      } [description]
     * @param  {[type]} preview:function(){                     }                 } [description]
     * @return {[type]}                      [description]
     */
    var ShopexPrinter = new Class({
        Extends: Printer,
        initialize: function(options){
            this.parent(options);

            this.ready = false;

            if (['object','function'].contains(typeof(this.options.activex)) && ('adjustpos' in this.options.activex == false) ) {
                // 打印插件未加载
                return ;
            }

            this.typeM = {
                'express':0,        // 快递单 （套打）
                'paged':1,          // 分页输出(标准)
                'page_all':2,       // 滚筒输出
                'auto_paged':3      // 自适应
            };

            if (this.options.data.length>0) this.loadReport(this.options.data,this.options.template,this.options.type);
        },
        isReady:function(){
            if (this.ready == false) {
                return false;
            }

            return true;
        },
        print:function(printer){
            if (!this.isReady()) {
                return false;
            }

            if (printer.offsetx>0 || printer.offsety>0){
                this.options.activex.adjustpos(printer.offsetx,printer.offsety,printer.name);
            }

            this.options.activex.printreport(printer.name,'express',0,printer.is_thermal);
            this.fireEvent('printComplete');

            return true;
        },
        preview:function(printer){
            return false;
        },
        getPrinters:function(){
            // if (!this.isReady()) {
            //     return false;
            // }

            var printerlist = this.options.activex.loadprinterlist();
            this.fireEvent('getPrinters', JSON.decode(printerlist));

            return true;
        },
        setPrinters:function(element){
            var data = this.options.activex.loadprinterlist();
            data = JSON.decode(data);

            return this.parent(element,data);
        },
        setPrinterConfig:function(printer){
            if (!this.isReady()) {
                this.fireEvent('error',{errmsg:'未安装SHOPEX打印控件！'});

                return false;
            }

            this.options.activex.printreport(printer.name,'express',1,printer.is_thermal);
            this.fireEvent('printerConfig');

            return true;
        },
        moveto:function(page){
            if (!this.isReady()) {
                return false;
            }

            this.options.activex.moveto(page);
            this.fireEvent('moveto');

            return true;
        },
        loadReport:function(data,template,type){
            try{
                this.options.activex.LoadReport.delay(20,this.options.activex,[template,data,this.typeM[type]]);
                this.ready = true;
            } catch(e) {
                alert(e.number);
            }

            return this;
        }
    });

    /**
     * 菜鸟打印控件
     * @param  {WebSocket} options){                         this.parent(options);            this.webSocket [description]
     * @return {[type]}               [description]
     */
    var CaiNiaoPrinter = new Class({
        Extends: Printer,
        initialize: function(options){
            this.parent(options);

            this.webSocket = new WebSocket('ws://127.0.0.1:13528');

            this.webSocket.onopen = function(event) {
                // 监听消息
                this.webSocket.onmessage = function(event)
                {
                    eval('var data = ' + event.data);
                    switch(data.cmd) {
                        case 'getPrinters':
                            this.fireEvent('getPrinters', data);break;
                        case 'printerConfig':
                            this.fireEvent('printerConfig', data);break;
                        case 'print':
                            if (data.previewImage) {
                                this.fireEvent('preview', data);break;
                            } else {
                                this.fireEvent('printComplete', data);break;
                            }
                        case 'notifyPrintResult':
                            if(data.taskStatus == 'printed') {
                                this.fireEvent('printSuccess', data);break;
                            } else if( data.taskStatus == 'failed' ) {
                                this.fireEvent('printFailure', data);break;
                            }
                    }
                }.bind(this);

                // 监听Socket的关闭
                this.webSocket.onclose = function(event)
                {
                    this.fireEvent('close');
                }.bind(this);

                this.fireEvent('open');
            }.bind(this);

            this.webSocket.onerror = function(event) 
            {
                this.fireEvent('error');
            }.bind(this);
        },
        isReady:function(){
            if (this.webSocket.readyState == 0) {
                this.fireEvent('error',{errmsg:'正在连接菜鸟打印组件，请稍后再试！'});

                return false;
            }

            return true;
        },
        setPrinterConfig:function(printer){
            if (!this.isReady()) {
                return false;
            }

            var request = this.getRequestObject('printerConfig');
            this.webSocket.send(JSON.stringify(request));

            return true;
        },
        print:function(printer){
            if (!this.isReady()) {
                return false;
            }

            this.formatData(this.options.data,printer.name,false).each(function(task){
                this.webSocket.send(JSON.stringify(task));
            }.bind(this));

            return true;
        },
        preview:function(printer){
            if (!this.isReady()) {
                return false;
            }

            this.formatData(this.options.data,printer.name,true).each(function(task){
                this.webSocket.send(JSON.stringify(task));
            }.bind(this));

            return true;
        },
        getPrinters:function(){
            if (!this.isReady()) {
                return false;
            }

            var request  = this.getRequestObject("getPrinters");
            this.webSocket.send(JSON.stringify(request));

            return true;
        },
        formatData:function(data,spooler,is_preview){
            var documents = [];

            data.each(function(printData){
                var jsonPacket = JSON.decode(printData.json_packet.replace(/“/g, '"'));
                if(!jsonPacket) {
                    alert('2016年8月24号之前获取的电子面单，\n或物流公司对应电子面单来源被更改，\n无法打印');
                    return documents;
                }

                var documentID = printData.batch_logi_no ? printData.batch_logi_no : printData.logi_no;
                doc = {
                    documentID:documentID,
                    contents:[]
                };

                // jsonPacket.data.waybillCode = doc.documentID;
                // jsonPacket.templateURL = this.options.template_url?this.options.template_url:jsonPacket.templateURL;
                doc.contents.push(jsonPacket);

                if (this.options.custom_template_url) {
                    var custom = {
                        templateURL:this.options.custom_template_url,
                        data:{}
                    };
                    
                    if (this.options.custom_data) {
                        this.options.custom_data.each(function(d){
                            custom['data'][d] = printData[d];
                        });
                    }
                    doc.contents.push(custom);
                }

                documents.push(doc);
            }.bind(this));

            return this.transPrintData(documents,spooler,is_preview);
        },
        transPrintData:function(documents,spooler,is_preview){
            var tasks = []; var taskID = 0;

            var taskDocNum = 10;
            for (var i = 0,len=documents.length;i<len;i+=taskDocNum) {
                var objWaybill = this.getRequestObject("print");
                objWaybill.task = {
                    taskID:taskID + '_' + this.getUUID(8,10),
                    preview:is_preview,
                    previewType:'image',
                    printer:spooler,
                    documents:[]
                };
                documents.slice(i,i+taskDocNum).each(function(val){
                    objWaybill.task.documents.push({
                        contents:val.contents,
                        documentID:(is_preview?1:0) + '_' + val.documentID
                    });
                });

                tasks.push(objWaybill);

                taskID++;
            }

            return tasks;
        },
        getUUID:function(len, radix){
            var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
            var uuid = [], i;
            radix = radix || chars.length;
            if (len) {
                for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
            } else {
                var r;
                uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
                uuid[14] = '4';
                for (i = 0; i < 36; i++) {
                    if (!uuid[i]) {
                        r = 0 | Math.random()*16;
                        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                    }
                }
            }
            return uuid.join('');
        },
        getRequestObject:function(cmd){
            var request  = new Object();
            request.requestID=this.getUUID(8, 16);
            request.version="1.0";
            request.cmd=cmd;
            return request;
        }
    });

    /**
     * LODOP打印控件
     * @param  {[type]} options){                         this.parent(options);            if (!document.getelementbyid('lodop-funcs')) {                var lodopFuncs [description]
     * @return {[type]}            [description]
     */
    var LodopPrinter = new Class({
        Extends: Printer,
        initialize: function(options){
            this.parent(options);

            if (document.getElementById('lodop-core')) document.getElementById('lodop-core').remove();

            var lodop = document.createElement("script");
            lodop.src = "/app/logisticsmanager/statics/js/lodop/main-bundle-89438.js?v=20190229";
            lodop.id = "lodop-core";

            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(lodop, s);

            this.ready = true;
        },
        print:function(printer){
            if (!this.isReady()) {
                return false;
            }

            LodopCore.print(JSON.parse(this.options.template),JSON.parse(this.options.data));

            this.fireEvent('printComplete');

            return true;
        },
        isReady:function(){
            if (this.ready == false) {
                return false;
            }

            return true;
        },
    });

    var PddPrinter = new Class({
        Extends: Printer,
        initialize: function(options){
            this.parent(options);

            this.webSocket = new WebSocket('ws://127.0.0.1:5000');

            this.webSocket.onopen = function(event) {
                // 监听消息
                this.webSocket.onmessage = function(event)
                {
                    eval('var data = ' + event.data);
                    switch(data.cmd) {
                        case 'getPrinters':
                            this.fireEvent('getPrinters', data);break;
                        case 'print':
                            this.fireEvent('printComplete', data);break;
                        case 'PrintResultNotify':
                            if(data.taskStatus == 'printed') {
                                this.fireEvent('printSuccess', data);break;
                            } else if( data.taskStatus == 'failed' ) {
                                this.fireEvent('printFailure', data);break;
                            }
                    }
                }.bind(this);

                // 监听Socket的关闭
                this.webSocket.onclose = function(event)
                {
                    this.fireEvent('close');
                }.bind(this);

                this.fireEvent('open');
            }.bind(this);

            this.webSocket.onerror = function(event)
            {
                this.fireEvent('error');
            }.bind(this);
        },
        isReady:function(){
            if (this.webSocket.readyState == 0) {
                this.fireEvent('error',{errmsg:'正在连接拼多多打印组件，请稍后再试！'});

                return false;
            }

            return true;
        },
        print:function(printer){
            if (!this.isReady()) {
                return false;
            }

            this.formatData(this.options.data,printer.name,false).each(function(task){
                this.webSocket.send(JSON.stringify(task));
            }.bind(this));

            return true;
        },
        preview:function(printer){
            if (!this.isReady()) {
                return false;
            }

            this.formatData(this.options.data,printer.name,true).each(function(task){
                this.webSocket.send(JSON.stringify(task));
            }.bind(this));

            return true;
        },
        getPrinters:function(){
            if (!this.isReady()) {
                return false;
            }

            var request  = this.getRequestObject("getPrinters");
            this.webSocket.send(JSON.stringify(request));

            return true;
        },
        formatData:function(data,spooler,is_preview){
            var documents = [];

            data.each(function(printData){
                var jsonPacket = JSON.decode(printData.json_packet.replace(/“/g, '"'));
                if(!jsonPacket) {
                    alert('数据结构不完整，\n无法打印');
                    return documents;
                }

                var documentID = printData.batch_logi_no ? printData.batch_logi_no : printData.logi_no;
                doc = {
                    documentID:documentID,
                    contents:[]
                };
                if(typeof jsonPacket == 'object' && !jsonPacket.encryptedData) {
                    doc.contents.push({data: jsonPacket, user_id:printData.user_id});
                } else {
                    jsonPacket.user_id = printData.user_id;
                    doc.contents.push(jsonPacket);
                }

                if (this.options.custom_template_url) {
                    var custom = {
                        templateURL:this.options.custom_template_url,
                        data:{}
                    };

                    if (this.options.custom_data) {
                        this.options.custom_data.each(function(d){
                            custom['data'][d] = printData[d];
                        });
                    }
                    doc.contents.push(custom);
                }

                documents.push(doc);
            }.bind(this));

            return this.transPrintData(documents,spooler,is_preview);
        },
        transPrintData:function(documents,spooler,is_preview){
            var tasks = []; var taskID = 0;

            var taskDocNum = is_preview ? 1 : 10;
            for (var i = 0,len=documents.length;i<len;i+=taskDocNum) {
                var objWaybill = this.getRequestObject("print");
                objWaybill.task = {
                    taskID:taskID + '_' + this.getUUID(8,10),
                    preview:is_preview,
                    printer:spooler,
                    documents:[]
                };
                documents.slice(i,i+taskDocNum).each(function(val){
                    objWaybill.task.documents.push({
                        contents:val.contents,
                        documentID:(is_preview?1:0) + '_' + val.documentID
                    });
                });
                tasks.push(objWaybill);

                taskID++;
            }

            return tasks;
        },
        getUUID:function(len, radix){
            var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
            var uuid = [], i;
            radix = radix || chars.length;
            if (len) {
                for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
            } else {
                var r;
                uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
                uuid[14] = '4';
                for (i = 0; i < 36; i++) {
                    if (!uuid[i]) {
                        r = 0 | Math.random()*16;
                        uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
                    }
                }
            }
            return uuid.join('');
        },
        getRequestObject:function(cmd){
            var request  = new Object();
            request.requestID=this.getUUID(8, 16);
            request.version="1.0";
            request.cmd=cmd;
            return request;
        }
    });
})();

